package com.zzedu.controller;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.zzedu.common.annotation.Log;
import com.zzedu.common.core.controller.BaseController;
import com.zzedu.common.core.domain.AjaxResult;
import com.zzedu.common.core.domain.entity.SysUser;
import com.zzedu.common.core.page.TableDataInfo;
import com.zzedu.common.enums.BusinessType;
import com.zzedu.common.enums.UserTypeEnumns;
import com.zzedu.common.exception.ServiceException;
import com.zzedu.common.utils.SecurityUtils;
import com.zzedu.common.utils.ServletUtils;
import com.zzedu.common.utils.StringUtils;
import com.zzedu.common.utils.poi.ExcelUtil;
import com.zzedu.domain.*;
import com.zzedu.dto.ZzClassesDTO;
import com.zzedu.dto.ZzSchoolDTO;
import com.zzedu.enmuns.ClzzTypeEnums;
import com.zzedu.framework.transaction.ITransactionHandlerService;
import com.zzedu.params.OperateStuClassRRelatedParams;
import com.zzedu.params.ZzClassesParams;
import com.zzedu.service.*;
import com.zzedu.vo.ZzClassesVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 班级管理Controller
 *
 * @author Mr.Wang
 * @date 2025-01-29
 */
@RestController
@RequestMapping("/school/classes")
public class ZzClassesController extends BaseController {
    @Autowired
    IZzClassesService zzClassesService;

    @Autowired
    IZzZzStuClassesRService zzZzStuClassesRService;

    @Autowired
    ITransactionHandlerService transactionHandlerService;

    @Autowired
    IZzTimetableService zzTimetableService;

    @Autowired
    IZzPictureBookService zzPictureBookService;

    @Autowired
    IZzCourseService zzCourseService;


    @Autowired
    IZzStuLogService zzStuLogService;

    /**
     * 查询班级管理列表
     */
    @PreAuthorize("@permission.hasAnyPermissions('school:classes:query')")
    @RequestMapping("/list")
    public TableDataInfo list(@RequestBody ZzClassesDTO zzClasses) {
        IPage<ZzClasses> page = zzClassesService.page(zzClasses.getPageDTO(), zzClassesService.buildQuery(zzClasses));
        return getDataTable(page, zzClassesService.convertVO(page.getRecords()));
    }

    /**
     * 导出班级管理列表
     */
    @PreAuthorize("@permission.hasAnyPermissions('school:classes:export')")
    @Log(title = "班级管理", businessType = BusinessType.EXPORT)
    @RequestMapping("/export")
    public void export(ZzClassesDTO zzClasses) {
        List<ZzClasses> list = zzClassesService.list(zzClassesService.buildQuery(zzClasses));
        ExcelUtil<ZzClassesVO> util = new ExcelUtil<ZzClassesVO>(ZzClassesVO.class);
        util.exportExcel(ServletUtils.getResponse(), zzClassesService.convertVO(list), "班级管理数据");
    }


    /**
     * 新增保存班级管理
     */
    @PreAuthorize("@permission.hasAnyPermissions('school:classes:add')")
    @Log(title = "班级管理", businessType = BusinessType.INSERT)
    @RequestMapping("/add")
    public AjaxResult addSave(@Validated @RequestBody ZzClassesParams zzClassesParams) {
        zzClassesParams.setStuCount(0L);
        SysUser sysUser = SecurityUtils.getSysUser();
        UserTypeEnumns useType = UserTypeEnumns.getCode(sysUser.getUserType());
        if (UserTypeEnumns.SCHOOL == useType) {
            zzClassesParams.setSchoolId(sysUser.getUserTypeId());
        }
        Assert.notNull(zzClassesParams.getSchoolId(), "校区不能为空");
        zzClassesService.save(zzClassesParams);
        return toAjax(true);
    }


    /**
     * 获取班级管理详细信息
     */
    @PreAuthorize("@permission.hasAnyPermissions('school:classes:query')")
    @RequestMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        ZzClasses zzClasses = zzClassesService.getById(id);
        ZzClassesVO zzClassesVO = zzClassesService.convertVO(Lists.newArrayList(zzClasses)).get(0);
        return success(zzClassesVO);
    }


    /**
     * 修改保存班级管理
     */
    @PreAuthorize("@permission.hasAnyPermissions('school:classes:edit')")
    @Log(title = "班级管理", businessType = BusinessType.UPDATE)
    @RequestMapping("/edit")
    public AjaxResult editSave(@Validated @RequestBody ZzClassesParams zzClassesParams) {
        zzClassesParams.setStuCount(null);
        SysUser sysUser = SecurityUtils.getSysUser();
        UserTypeEnumns useType = UserTypeEnumns.getCode(sysUser.getUserType());
        if (UserTypeEnumns.SCHOOL == useType) {
            zzClassesParams.setSchoolId(sysUser.getUserTypeId());
        }
        return toAjax(zzClassesService.save(zzClassesParams));
    }

    /**
     * 删除班级管理
     */
    @PreAuthorize("@permission.hasAnyPermissions('school:classes:remove')")
    @Log(title = "班级管理", businessType = BusinessType.DELETE)
    @RequestMapping("/remove/{ids}")
    public AjaxResult remove(@PathVariable List<Long> ids) {
        return toAjax(zzClassesService.removeBatchByIds(ids));
    }


    /**
     * 增加、删除班级学生
     *
     * @return
     */
    @PreAuthorize("@permission.hasAnyPermissions('school:classes:edit')")
    @Log(title = "增加、删除班级学生", businessType = BusinessType.UPDATE)
    @RequestMapping("/manStudent")
    public AjaxResult manStudent(@Validated @RequestBody OperateStuClassRRelatedParams operateStuClassRRelatedParams) {
        Assert.isTrue(!CollectionUtils.isEmpty(operateStuClassRRelatedParams.getStuIdList()), "学生不能为空");
        return success(transactionHandlerService.runInTransaction(() -> {
            /**
             * 1-关联
             * 2-移除
             */
            if (2 == operateStuClassRRelatedParams.getOp()) {
                zzZzStuClassesRService.remove(Wrappers.lambdaQuery(ZzStuClassesR.class).eq(ZzStuClassesR::getClassId, operateStuClassRRelatedParams.getId())
                        .in(ZzStuClassesR::getStuId, operateStuClassRRelatedParams.getStuIdList())
                );
                for (Long id : operateStuClassRRelatedParams.getStuIdList()) {
                    ZzStuLog zzStuLog = new ZzStuLog();
                    zzStuLog.setAction(1);
                    zzStuLog.setStuId(id);
                    zzStuLog.setOper(2L);
                    zzStuLogService.save(zzStuLog);
                }
            } else if (1 == operateStuClassRRelatedParams.getOp()) {
                ZzClasses zzClasses = this.zzClassesService.getById(operateStuClassRRelatedParams.getId());
                String level = zzClasses.getLevel();
                LambdaQueryWrapper<ZzStuClassesR> checkWrapper = Wrappers.lambdaQuery(ZzStuClassesR.class);
                checkWrapper.apply("class_id in(select id from zz_classes where level<>{0} and  deleted=0)", level);
                checkWrapper.in(ZzStuClassesR::getStuId, operateStuClassRRelatedParams.getStuIdList());
                checkWrapper.last("limit 1");
                if (null != zzZzStuClassesRService.getOne(checkWrapper)) {
                    throw new ServiceException("当前分班学生中存在夸级学生,请先移除");
                }
                for (Long id : operateStuClassRRelatedParams.getStuIdList()) {
                    if (null == zzZzStuClassesRService.getOne(Wrappers.lambdaQuery(ZzStuClassesR.class)
                            .eq(ZzStuClassesR::getClassId, operateStuClassRRelatedParams.getId())
                            .eq(ZzStuClassesR::getStuId, id)
                            .last("limit 1"))) {
                        ZzStuLog zzStuLog = new ZzStuLog();
                        zzStuLog.setAction(1);
                        zzStuLog.setStuId(id);
                        zzStuLog.setOper(2L);
                        zzStuLogService.save(zzStuLog);
                    }
                }
                zzZzStuClassesRService.remove(Wrappers.lambdaQuery(ZzStuClassesR.class).eq(ZzStuClassesR::getClassId, operateStuClassRRelatedParams.getId())
                        .in(ZzStuClassesR::getStuId, operateStuClassRRelatedParams.getStuIdList())
                );
                //当前班级课表
                List<ZzTimetable> zzTimetableList = zzTimetableService.list(Wrappers.lambdaQuery(ZzTimetable.class).eq(ZzTimetable::getClzzId, operateStuClassRRelatedParams.getId())
                        .orderByAsc(ZzTimetable::getStudyDate)
                );
                for (Long id : operateStuClassRRelatedParams.getStuIdList()) {
                    //学生的所有班级课表
                    List<Long> clzzId = zzZzStuClassesRService.list(Wrappers.lambdaQuery(ZzStuClassesR.class)
                                    .eq(ZzStuClassesR::getStuId, id))
                            .stream().map(ZzStuClassesR::getClassId).collect(Collectors.toList());
                    if (CollectionUtils.isEmpty(clzzId)) {
                        clzzId = Lists.newArrayList();
                    }
                    clzzId.add(-1L);
                    List<ZzTimetable> stuZzTimetableList =
                            zzTimetableService.list(Wrappers.lambdaQuery(ZzTimetable.class)
                                    .in(ZzTimetable::getClzzId,clzzId ).orderByAsc(ZzTimetable::getStudyDate));
                    if (!CollectionUtils.isEmpty(stuZzTimetableList)) {
                        if (zzTimetableService.hasTimeConflict(zzTimetableList, stuZzTimetableList)) {
                            throw new ServiceException("有学生班级存在课表冲突,请先移除");
                        }
                    }
                }
                List<ZzStuClassesR> zzStuClassesRList = operateStuClassRRelatedParams.getStuIdList().stream().map(stuId -> {
                    ZzStuClassesR zzStuClassesR = new ZzStuClassesR();
                    zzStuClassesR.setStuId(stuId);
                    zzStuClassesR.setClassId(operateStuClassRRelatedParams.getId());
                    return zzStuClassesR;
                }).collect(Collectors.toList());
                zzZzStuClassesRService.saveBatch(zzStuClassesRList);
            }
            return true;
        }));
    }
}
